import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import jp.hishidama.eval.ExpRuleFactory;
import jp.hishidama.eval.Expression;
import jp.hishidama.eval.Rule;

import org.jibble.pircbot.PircBot;

import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;

public class MyBot extends PircBot {

	public String nickName;
	
	//===========================================================
	// 各種メモリデータ
	//===========================================================
	public Map<String, String> map = new HashMap<String, String>();
	public Map<String, String> dengonmap = new HashMap<String, String>();
	public Map<String, String> userDatamap = new HashMap<String, String>();
	public Map<String, String> urlDatamap = new LinkedHashMap<String, String>();

	private static String fileName 			= "c:\\out.txt";
	private static String dengonFileName	= "c:\\dengon.txt";
	private static String userDataFileName	= "c:\\userData.txt";
	private static String urlData			= "c:\\urlData.txt";
//	private static String SYSTEM_CONFIG = "systemConfig.txt";
	
	/* Shift_JIS, ISP-2022-JP, EUC-JP Windows-31J */
	/* 出力時に　JISAutoDetect　の指定は不可 */
	private static String outFileCoding = "Shift_JIS";
	
	// 座布団の初期枚数
	private static String INIT_ZABUTON = "1";
	
    /**
     * Constructor
     */
	public MyBot() {
		this.setName(nickName);
		this.setName("WAT_bot");
		// 学習データ読み込み
		fileRead(fileName, this.map);
		// 伝言読み込み
		fileRead(dengonFileName, this.dengonmap);
		// ユーザデータ読み込み
		fileRead(userDataFileName, this.userDatamap);
		// URLデータ読み込み
		fileRead(urlData, this.urlDatamap);
	}

    /* (非 Javadoc)
     * 強制切断時、復帰用
     * 
     * @see org.jibble.pircbot.PircBot#onDisconnect()
     */
    @Override
	public void onDisconnect() {
		while (!isConnected()) {
			try {
				reconnect();
			} catch (Exception e) {
				// Couldn't reconnect!
				// Pause for a short while...?
			}
		}
	}
    
    /* (非 Javadoc)
     * チャンネルに接続した時の動作
     * 
     * @see org.jibble.pircbot.PircBot#onJoin(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
     */
    @Override
	public void onJoin(String channel, String sender, String login, String hostname) {
    	// 名前解決
    	String _login = login.substring(1);
    	
    	if (!getNick().equals(sender) && !sender.equals("fem")) {
			sendMessage(channel, _login + "さん、こんにちは！");

			// 座布団を読み込む
			readZabuton(channel, sender, _login, hostname);
		}

		// 伝言機能
		sendDengon(channel, sender, _login, hostname);
	}

	/* (非 Javadoc)
	 * IRCメッセージの内容を取得し、処理を行う
	 * 
	 * @see org.jibble.pircbot.PircBot#onMessage(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
    @Override
	public void onMessage(String channel, String sender, String login, String hostname, String message) {

    	// 名前解決
    	String _login = login.substring(1);
    	
		// ヘルプ表示
		if (viewHelpAll(channel, sender, login, hostname, message)) {
			return;
		}

		// チャンネル参加
		if (joinChanelByMsg(channel, sender, login, hostname, message)) {
			return;
		}

		// チャンネル退出
		if (exitChanelByMsg(channel, sender, login, hostname, message)) {
			return;
		}

		// なると機能
		// 発言ユーザ名は名前解決しない
		if (giveNaruto(channel, sender, login, hostname, message)) {
			return;
		}

		// 学習機能
		if (registReturnMsg(channel, sender, login, hostname, message)) {
			return;
		}

		// 取消し機能
		if (deleteReturnMsg(channel, sender, login, hostname, message)) {
			return;
		}

		// 伝言機能
		if (registDengonMsg(channel, sender, _login, hostname, message)) {
			return;
		}

		// HTTP機能
		if (getHttpUrlSiteData(channel, sender, login, hostname, message)) {
			return;
		}

		// 計算機能
		if (calcStrData(channel, sender, login, hostname, message)) {
			return;
		}

		// ツイッター機能
		if (getTwitterMsg(channel, sender, login, hostname, message)) {
			return;
		}

		// 座布団機能
		if (updateZabuton(channel, sender, login, hostname, message)) {
			return;
		}

		// URL履歴表示
		if (showUrl(channel, message)) {
			return;
		}

		// メッセージ内に特定キーワードがあると返答
		autoReturnMsg(channel, sender, login, hostname, message);
	}

	/**
	 * ヘルプメッセージを表示する
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean viewHelpAll(String channel, String sender, String login, String hostname, String message) {
		if (message.matches("^ヘルプ表示$")) {
			// 機能のヘルプを表示する
			sendMessage(channel, "＠配布機能：なるとくれ");
			sendMessage(channel, "チャンネル参加機能：チャンネルに入れ「#チャンネル名」");
			sendMessage(channel, "伝言機能：「ニックネーム」に「ないよう」と伝えて");
			sendMessage(channel, "学習方法：「きーわーど」は「返事」だ");
			sendMessage(channel, "取消方法：「きーわーど」は忘れて");
			sendMessage(channel, "変数：%name = 名前");
			sendMessage(channel, "計算機能：=計算式");
			sendMessage(channel, "ツイッター取得：tw=アカウント名");
			sendMessage(channel, "山田君機能：ニックネーム に座布団[?枚]持ってきて、ニックネーム の座布団[?枚 or 全部]持っていって　※[]部分は省略可能");
			sendMessage(channel, "URL履歴機能：URL履歴 数量 ※数量省略可能");
			return true;
		}
		return false;
	}

	/**
	 * サイトのタイトルを返却する機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean getHttpUrlSiteData(String channel, String sender, String login, String hostname, String message) {

		// メッセージ内容がURLの場合
		if (message.matches("^http://.*")) {
			try {
				URL url = new URL(message);

				HttpURLConnection urlconn = (HttpURLConnection) url.openConnection();
				urlconn.setRequestMethod("GET");
				urlconn.setInstanceFollowRedirects(false);
				urlconn.setRequestProperty("Accept-Language", "ja;q=0.7,en;q=0.3");

				urlconn.connect();

				String mojiCode = "JISAutoDetect";

				BufferedReader reader = new BufferedReader(new InputStreamReader(urlconn.getInputStream(), "JISAutoDetect"));
				if (message.matches("^http://www\\.youtube\\.com/.*")) {
					mojiCode = "UTF-8";
				}
				
				while (true) {
					String line = reader.readLine();
					if (line == null) {
						break;
					}

				    line = line.trim();
				    line = line.replaceFirst("\t", "");

					// 小文字、大文字対応、そのうち綺麗に修正する
					if (line.matches("<meta.*charset=.*")) {
						String[] strAry = line.split("charset=");
						if (strAry.length > 0) {
							String chrstr = strAry[1].replaceAll("\"", "");
							System.out.println(chrstr);

							// 文字コード判定
							if (chrstr.matches(".*utf.*") || chrstr.matches(".*UTF.*")) {
								mojiCode = "UTF-8";
							} else if (chrstr.matches(".*Shift.*")) {
								mojiCode = "Shift_JIS";
							} else if (chrstr.matches(".*euc.*") || chrstr.matches(".*EUC.*")) {
								mojiCode = "EUC_JP";
							}
							break;
						}
					} else if (line.matches("<META.*charset=.*")) {
						String[] strAry = line.split("charset=");
						if (strAry.length > 0) {
							String chrstr = strAry[1].replaceAll("\"", "");
							System.out.println(chrstr);

							// 文字コード判定
							if (chrstr.matches(".*utf.*") || chrstr.matches(".*UTF.*")) {
								mojiCode = "UTF-8";
							} else if (chrstr.matches(".*Shift.*")) {
								mojiCode = "Shift_JIS";
							} else if (chrstr.matches(".*euc.*") || chrstr.matches(".*EUC.*")) {
								mojiCode = "EUC_JP";
							}
							break;
						}
					}

				}
				
				reader.close();
				urlconn.disconnect();

				HttpURLConnection urlconn2 = (HttpURLConnection) url.openConnection();
				urlconn2.setRequestMethod("GET");
				urlconn2.setInstanceFollowRedirects(false);
				urlconn2.setRequestProperty("Accept-Language", "ja;q=0.7,en;q=0.3");

				urlconn2.connect();

				BufferedReader reader2 = new BufferedReader(new InputStreamReader(urlconn2.getInputStream(), mojiCode));

				// タイトル文字列
				String title = "";
				
				// youtube タイトル対策
				boolean youtubeFlag = false;
				if (message.matches("^http://www\\.youtube\\.com/.*")) {
					youtubeFlag = true;
				}

				// タイトル取得中対策
				boolean titleInFlag = false;

				while (true) {
					String line = reader2.readLine();
					if (line == null) {
						break;
					}

					// 空白除去
					line = line.trim();

					// YOUTUBE専用処理
					if (youtubeFlag) {
						if (line.matches("<meta name=\"title\".*")) {
							String[] strAry = line.split("<meta name=\"title\" content=\"");

							if (strAry.length > 0) {
								title = strAry[1].replace("\">", "");
								sendMessage(channel, title);
							}
							break;
						}

					} else {

						// タイトル取得処理中の場合
						if (titleInFlag) {
							title += line;
						}

						// 通常のサイトはこっちで判定
						if (line.matches("^<title>.*") || line.matches("^<TITLE>.*")) {
							line = line.replace("<title>", "");
							line = line.replace("<TITLE>", "");
							title = line;

							// タイトル取得中にする
							titleInFlag = true;

						}

						// タイトル終了タグがあれば、タイトル取得処理を終了し、
						// タイトルを表示する
						if (line.matches(".*</title>$") || line.matches(".*</TITLE>$")) {

							title = title.replace("</title>", "");
							title = title.replace("</TITLE>", "");

							sendMessage(channel, title);
							break;
						}

					}

				}
				
				reader2.close();
				urlconn2.disconnect();

				registUrl(channel, message);
				return true;

			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		return false;
	}
	
	/**
	 * @param channel
	 * @param message
	 */
	private void registUrl(String channel, String message) {

		if (this.urlDatamap.containsValue(message)) {
			sendMessage(channel, "既出です");
		} else {
			// 現時刻の日付文字列の取得
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
			String date = sdf.format(new Date());

			// URLを記録する
			this.urlDatamap.put(date, message);

			// ファイルに記録
			fileWrite(this.urlDatamap, urlData);
		}

	}
	
	/**
	 * 記録されたURLを指定数分だけ表示する
	 * 
	 * @param channel
	 * @param message
	 * @return
	 */
	public boolean showUrl(String channel, String message) {

		if (message.matches("^URL履歴.*$")) {

			String url = "";
			int count = 1;

			try {
				String[] tmp = message.split(" ");
				if (tmp.length > 0) {
					count = Integer.parseInt(tmp[1]);
				}

			} catch (Exception e) {
				count = 1;
			}
			
			Object[] key = this.urlDatamap.keySet().toArray();
			Arrays.sort(key);
			int j = 0;
			for(int i = key.length-1 ; i >= 0 ; i --) {
				
				if (count <= j) {
					break;
				}
				String value = this.urlDatamap.get(key[i]);
				url += " " + value;
				j++;
			}

			sendMessage(channel, url);
			return true;

		}
		return false;

	}
	
	/**
	 * 座布団データを読み込む
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 */
	public void readZabuton(String channel, String sender, String login, String hostname) {
		if (this.userDatamap.containsKey(login)) {
			// 座布団がある場合、枚数を表示
			String value = this.userDatamap.get(login);
			sendMessage(channel, login + "さんの座布団は、" + value + "枚です.");
		} else {
			// 座布団がない場合、新規に作成する
			createZabuton(channel, login);
		}
	}
	
	/**
	 * 座布団データを新規登録する
	 * @param channel
	 * @param sender
	 */
	public void createZabuton(String channel, String login) {
		// 座布団データの登録
		this.userDatamap.put(login, INIT_ZABUTON);

		// ファイルに記録
		fileWrite(this.userDatamap, userDataFileName);

		// 座布団登録後メッセージ表示
		sendMessage(channel, login + "さんの座布団は、" + INIT_ZABUTON + "枚です.");
	}
	
	/**
	 * 座布団持ってきて、持っていって機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean updateZabuton(String channel, String sender, String login, String hostname, String message) {

		if (message.matches("^.* に座布団.*持ってきて$")) {
			String target = "";
			String msg = "";

			// 禁止文字を置き換えて削除する
			message = message.replaceAll(",", "");

			String[] strAry = message.split(" ");
			if (strAry.length > 1) {
				// 対象を設定
				target = strAry[0];
				// バリュー部分を生成
				msg = strAry[1];

				// 枚数
				int maisuu = 1;

				// 枚数指定がある場合、枚数を取得し設定する
				String[] zabutonAry = msg.split("枚");
				if (zabutonAry.length > 1) {
					String tmp = zabutonAry[0].replaceAll("に座布団", "");
					try {
						maisuu = Integer.parseInt(tmp);
					} catch (NumberFormatException e) {
						maisuu = 1;
					}
				}
				
		    	// 名前解決
		    	String _target = nameResolve(target);

				// 座布団がある場合
				if (this.userDatamap.containsKey(_target)) {
					String value = this.userDatamap.get(_target);
					int zcount = Integer.parseInt(value);
					zcount += maisuu;

					// 座布団データの登録
					this.userDatamap.put(_target, String.valueOf(zcount));

					// ファイルに記録
					fileWrite(this.userDatamap, userDataFileName);

					// 座布団登録後メッセージ表示
					sendMessage(channel, "はい、かしこまりました");
					sendMessage(channel, _target + "さんの座布団は、" + zcount + "枚です.");
				}
				// 座布団がない場合、警告メッセージ
				else {
					sendMessage(channel, "ユーザデータが存在しません");
				}

				return true;
			}
		} else if (message.matches("^.* の座布団.*持っていって$")) {
			String target = "";
			String msg = "";

			// 禁止文字を置き換えて削除する
			message = message.replaceAll(",", "");

			String[] strAry = message.split(" ");
			if (strAry.length > 1) {
				// 対象を設定
				target = strAry[0];
				// バリュー部分を生成
				msg = strAry[1];

				// 枚数
				int maisuu = 1;

				// 枚数指定がある場合、枚数を取得し設定する
				String[] zabutonAry = msg.split("枚");
				String[] zabutonAllAry = msg.split("全部");
				if (zabutonAry.length > 1) {
					String tmp = zabutonAry[0].replaceAll("の座布団", "");
					try {
						maisuu = Integer.parseInt(tmp);
					} catch (NumberFormatException e) {
						maisuu = 1;
					}

				} else if (zabutonAllAry.length > 1) {
					maisuu = Integer.MAX_VALUE;
				}
				
		    	// 名前解決
				String _target = nameResolve(target);

				// 座布団がある場合
				if (this.userDatamap.containsKey(_target)) {
					String value = this.userDatamap.get(_target);
					int zcount = Integer.parseInt(value);
					zcount -= maisuu;
					
					// 既に座布団がないとき
					if (zcount < 0) {
						sendMessage(channel, _target + "さんの座布団は無くなりました");
						zcount = 0;
					} else {
						// 座布団メッセージ表示
						sendMessage(channel, "はい、かしこまりました");
						sendMessage(channel, _target + "さんの座布団は、" + zcount + "枚です.");
					}

					// 座布団データの登録
					this.userDatamap.put(_target, String.valueOf(zcount));

					// ファイルに記録
					fileWrite(this.userDatamap, userDataFileName);
				}
				// 座布団がない場合、警告メッセージ
				else {
					sendMessage(channel, "ユーザデータが存在しません");
				}

				return true;
			}
		}

		return false;
	}
	
	/**
	 * 伝言送信機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 */
	public void sendDengon(String channel, String sender, String login, String hostname) {
		
		// 伝言MAPにユーザー名のkeyが存在する場合処理
		if (dengonmap.containsKey(login)) {
			String value = this.dengonmap.get(login);
			sendMessage(channel, value);
			this.dengonmap.remove(login);
			
			// ファイルに記録
			fileWrite(this.dengonmap, dengonFileName);
		}
	}

	/**
	 * 伝言登録機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean registDengonMsg(String channel, String sender, String login, String hostname, String message) {

		// 「」に「」と伝えて
		if (message.matches("^「.*」に「.*」と伝えて$")) {
			String target = "";
			String msg = "";

			// 禁止文字を置き換えて削除する
			message = message.replaceAll(",", "");

			String[] strAry = message.split("」に「");
			if (strAry.length > 1) {
				// 対象を設定
				target = strAry[0].replaceFirst("「", "");
				// バリュー部分を生成
				msg = strAry[1].replaceAll("」と伝えて", "");
				
				if (!userDatamap.containsKey(target)) {
					sendMessage(channel, "該当ユーザデータが存在しません");
					return false;
				}

				// お送り主を先頭にもってくる
				msg = login + "様から、" + msg;

				// 伝言データを登録
				this.dengonmap.put(target, msg);

				// ファイルに記録
				fileWrite(this.dengonmap, dengonFileName);

				sendMessage(channel, "「" + target + "」さんに「" + msg + "」と伝えます。");
				return true;
			}
		}
		return false;
	}

	/**
	 * チャンネル参加コマンド機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean joinChanelByMsg(String channel, String sender, String login, String hostname, String message) {

		if (message.matches("^チャンネルに入れ「.*」$")) {
			String[] strAry = message.split("」");
			if (strAry.length > 0) {
				String chn = "";
				chn = strAry[0].replaceFirst("チャンネルに入れ「", "");

				joinChannel(chn);
			}
			return true;
		}
		
		return false;
	}

	/**
	 * チャンネル退出機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean exitChanelByMsg(String channel, String sender, String login, String hostname, String message) {
		if (message.matches("^チャンネルから出ろ「.*」$")) {
			String[] strAry = message.split("」");
			if (strAry.length > 0) {
				String chn = "";
				chn = strAry[0].replaceFirst("チャンネルから出ろ「", "");

				partChannel(chn);
			}
			return true;
		}

		return false;
	}

	/**
	 * なると配布機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean giveNaruto(String channel, String sender, String login, String hostname, String message) {

		if (message.matches("^なるとくれ")) {
			op(channel, sender);
			return true;

		}

		return false;
	}

	/**
	 * 学習機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean registReturnMsg(String channel, String sender, String login, String hostname, String message) {

		// "「」は「」だ";
		if (message.matches("^「.*」は「.*」だ$")) {

			String key = "";
			String value = "";
			// 禁止文字を置き換えて削除する
			message = message.replaceAll(",", "");

			String[] strAry = message.split("」は「");

			if (strAry.length > 1) {
				// キー部分を生成
				key = strAry[0].replaceFirst("「", "");
				// バリュー部分を生成
				value = strAry[1].replaceAll("」だ", "");
				// 　でばっぐようログ出力
				System.out.println("key:" + key + "  value:" + value + "  sender:" + sender + "  hostname:" + hostname);

				this.map.put(key, value);
				// ファイルに記録
				fileWrite(this.map, fileName);

				// 言葉覚えたので、その返答
				sendMessage(channel, "「" + key + "」は「" + value + "」ですね！");

				return true;
			}
		}
		return false;
	}

	/**
	 * 取消し機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean deleteReturnMsg(String channel, String sender, String login, String hostname, String message) {

		// "「」は忘れて";
		if (message.matches("^「.*」は忘れて$")) {

			String key = "";

			String[] strAry = message.split("」は忘れて");

			if (strAry.length > 0) {
				// キー部分を生成
				key = strAry[0].replaceFirst("「", "");

				// 　でばっぐようログ出力
				System.out.println("削除 key:" + key);

				if (this.map.containsKey(key)) {
					this.map.remove(key);
				}

				// ファイルに記録
				fileWrite(this.map, fileName);

				// 言葉忘れたので、その返答
				sendMessage(channel, "「" + key + "」を忘れました");

				return true;
			}
		}
		return false;
	}

	/**
	 * メッセージに特定キーワードがあると、反応し発言する ただし、キーワードmapの先頭から割り当てる
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 */
	public void autoReturnMsg(String channel, String sender, String login, String hostname, String message) {
		for (String key : this.map.keySet()) {
			if (message.indexOf(key) != -1) {
				String value = this.map.get(key);
				value = value.replaceAll("%name", login);
				sendMessage(channel, value);
				break;
			}
		}
	}
	
	/**
	 * すべてファイルに出力する
	 * 
	 * @param parmmap
	 * @param fileName
	 */
	public void fileWrite(Map<String, String> parmmap, String fileName) {
		
		BufferedWriter outFile = null;
		
		try {
			outFile = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), outFileCoding));

			for (String key : parmmap.keySet()) {
				String value = parmmap.get(key);
				outFile.write(key + "," + value);
				outFile.newLine();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// クローズ処理
				outFile.flush();
				outFile.close();
			} catch (IOException e) {
				e.printStackTrace();
			}	
		}
	}
	
	/**
	 * 学習した言葉のファイルを入力し、メモリに保持
	 * 
	 * @param filename
	 * @param parmmap
	 */
	public void fileRead(String filename, Map<String, String> parmmap) {

		FileInputStream fi3 = null;
		InputStreamReader ir3 = null;
		BufferedReader br3 = null;

		try {

			File chkFile = new File(filename);
			if (!chkFile.exists()) {
				chkFile.createNewFile();
			}

			fi3 = new FileInputStream(filename);
			ir3 = new InputStreamReader(fi3, outFileCoding);
			br3 = new BufferedReader(ir3);

			// 読み込み
			System.out.println("一行ずつ読む");
			String line;
			// 全データをいったん削除
			parmmap.clear();
			while ((line = br3.readLine()) != null) {
				// 改行がカットされてるので、printlnになる。
				System.out.println(line);
				String key = "";
				String value = "";
				String[] tmp = line.split(",");
				if (tmp.length > 1) {
					key = tmp[0];
					value = tmp[1];

					parmmap.put(key, value);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				// クローズ処理
				fi3.close();
				ir3.close();
				br3.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 計算機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	public boolean calcStrData(String channel, String sender, String login, String hostname, String message) {
		try {
			if (message.matches("^=.*")) {
				message = message.replaceFirst("=", "");

				Rule rule = ExpRuleFactory.getDefaultRule();
				Expression exp = rule.parse(message);
				long result = exp.evalLong(); // 計算実施

				sendMessage(channel, String.valueOf(result));
				return true;
			}
			
			return false;
		} catch (Exception e) {
			return false;
		} 
	}
	
	/**
	 * ツイッターの特定ユーザメッセージ取得機能
	 * 
	 * @param channel
	 * @param sender
	 * @param login
	 * @param hostname
	 * @param message
	 * @return
	 */
	// TODO これはテストです。完成後いろいろ直す！
	public boolean getTwitterMsg(String channel, String sender, String login, String hostname, String message) {
		try {
			if (message.matches("^tw=.*")) {
				message = message.replaceFirst("tw=", "");

				// ツイッターのアカウント名
				String screenName = "";
				// 最大取得数の初期値
				int maxMsgCount = 1;

				// スペースで分割する
				String[] msgAry = message.split(" ");

				// 対象のアカウント名
				if (msgAry.length > 0) {
					screenName = msgAry[0];
				}

				// 最大取得数の設定、特に指定なしの場合、最新だけ
				// エラー時はすべて最新だけ
				if (msgAry.length > 1) {
					String tmp = msgAry[1];
					try {
						maxMsgCount = Integer.parseInt(tmp);
						if (maxMsgCount > 10) {
							maxMsgCount = 10;
						}
					} catch (NumberFormatException e) {
						// 何もしない
					}

				}

				String result = "";

				// requesting page 1, number of elements per page is 10
				Paging paging = new Paging(1, maxMsgCount);
				// このファクトリインスタンスは再利用可能でスレッドセーフです
				Twitter twitter = new TwitterFactory().getInstance();
				List<Status> statuses = twitter.getUserTimeline(screenName, paging);

				result = screenName + "：";

				for (Status status : statuses) {
					// 改行文字を削除して、発言
					sendMessage(channel, result + status.getText().replaceAll("\\r", "").replaceAll("\\n", ""));
				}

				return true;
			}
			
			return false;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * 名前解決
	 * 
	 * @param sender
	 * @return
	 */
	private String nameResolve(String target) {
		
    	String userName = target;
	    for (String key : userDatamap.keySet()) {
	    	if(target.startsWith(key)){
	    		userName = key;
	    	}
	    }
		return userName;
	}
	
}
